﻿using System;
using System.Text;
using System.Drawing;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct complex
{
    public double R { get; set; } = 0;
    public double I { get; set; } = 0;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="real"></param>
    /// <param name="imag"></param>
    public complex(double real = 0, double imag = 0)
    {
        R = real;
        I = imag;
    }

    public complex(double[] v)
    {
        R = v[0];
        I = v[1];
    }

    public double[] toArray()
    {
        return new double[2] { R, I };
    }

    /// <summary>
    /// 复数输出
    /// </summary>
    public new string ToString()
    {
        //cout << "(" << R << ", " << I << ")";
        //输出形式为:(实部, 虚部)
        return R + " + " + I + " i";
    }

    /// <summary>
    /// 复数模
    /// </summary>
    /// <returns></returns>
    public double cfabs()
    {
        double y;
        y = R * R + I * I;
        if (y < float.Epsilon) return y;
        return Math.Sqrt(y);
    }

    /// <summary>
    /// 复数幅角
    /// </summary>
    /// <returns></returns>
    public double angle()
    {
        double y;
        y = Math.Atan2(I, R);
        return (y);
    }

    /// <summary>
    /// 复数加法
    /// </summary>
    /// <param name="c2"></param>
    /// <returns></returns>
    public static complex operator +(complex c1, complex c2)
    {
        complex c = new complex();
        c.R = c1.R + c2.R;
        c.I = c1.I + c2.I;
        return c;
    }

    /// <summary>
    /// 复数减法
    /// </summary>
    /// <param name="c1"></param>
    /// <param name="c2"></param>
    /// <returns></returns>
    public static complex operator -(complex c1, complex c2)
    {
        complex c = new complex();
        c.R = c1.R - c2.R;
        c.I = c1.I - c2.I;
        return c;
    }

    /// <summary>
    /// 复数乘法
    /// </summary>
    /// <param name=""></param>
    /// <param name=""></param>
    /// <returns></returns>
    public static complex operator *(complex c1, complex c2)
    {
        complex c = new complex();
        double p, q, s;
        p = c1.R * c2.R;
        q = c1.I * c2.I;
        s = (c1.R + c1.I) * (c2.R + c2.I);
        c.R = p - q;
        c.I = s - p - q;
        return c;
    }

    /// <summary>
    /// 复数除法
    /// </summary>
    /// <param name="c1"></param>
    /// <param name="c2"></param>
    /// <returns></returns>
    public static complex operator /(complex c1, complex c2)
    {
        complex c = new complex();
        double p, q, s, w;
        p = c1.R * c2.R; q = -c1.I * c2.I;
        s = (c1.R + c1.I) * (c2.R - c2.I);
        w = (c2.R) * (c2.R) + (c2.I) * (c2.I);
        //if (w + 1.0 != 1.0)
        if (Math.Abs(w) > float.Epsilon)
        {
            c.R = (p - q) / w;
            c.I = (s - p - q) / w;
        }
        else
        {
            c.R = 1e+300;
            c.I = 1e+300;
        }
        return c;
    }

    /// <summary>
    /// 复数乘幂
    /// </summary>
    /// <param name="n"></param>
    /// <returns></returns>
    public complex cpower(int n)
    {
        complex c = new complex();
        double r, q;
        q = Math.Atan2(I, R);
        r = Math.Sqrt(R * R + I * I);
        //if (r + 1.0 != 1.0)
        if (Math.Abs(r) > float.Epsilon)
        {
            r = n * Math.Log(r);
            r = Math.Exp(r);
        }
        c.R = r * Math.Cos(n * q);
        c.I = r * Math.Sin(n * q);
        return c;
    }

    /// <summary>
    /// 复数的n次方根
    /// </summary>
    /// <param name="n"></param>
    /// <param name="p"></param>
    public void croot(int n, complex[] p)
    {
        complex c = new complex();
        int k;
        double r, q, t;
        if (n < 1) return;
        q = Math.Atan2(I, R);
        r = Math.Sqrt(R * R + I * I);
        if (r + 1.0 != 1.0)
        {
            r = (1.0 / n) * Math.Log(r);
            r = Math.Exp(r);
        }
        p = new complex[n];
        for (k = 0; k < n; k++)
        {
            t = (2.0 * k * 3.1415926 + q) / n;
            c.R = r * Math.Cos(t);
            c.I = r * Math.Sin(t);
            p[k] = c;
        }
    }

    /// <summary>
    /// 复数指数
    /// </summary>
    /// <returns></returns>
    public complex cexp()
    {
        complex c = new complex();
        double p;
        p = Math.Exp(R);
        c.R = p * Math.Cos(I);
        c.I = p * Math.Sin(I);
        return c;
    }

    /// <summary>
    /// 复数对数
    /// </summary>
    /// <returns></returns>
    public complex clog()
    {
        complex c = new complex();
        double p;
        p = R * R + I * I;
        p = Math.Log(Math.Sqrt(p));
        c.R = p;
        c.I = Math.Atan2(I, R);
        return c;
    }

    /// <summary>
    /// 复数正弦
    /// </summary>
    /// <returns></returns>
    public complex csin()
    {
        complex c = new complex();
        double p, q;
        p = Math.Exp(I);
        q = Math.Exp(-I);
        c.R = Math.Sin(R) * (p + q) / 2.0;
        c.I = Math.Cos(R) * (p - q) / 2.0;
        return c;
    }

    /// <summary>
    /// 复数余弦
    /// </summary>
    /// <returns></returns>
    public complex ccos()
    {
        complex c = new complex();
        double p, q;
        p = Math.Exp(I);
        q = Math.Exp(-I);
        c.R = Math.Cos(R) * (p + q) / 2.0;
        c.I = -Math.Sin(R) * (p - q) / 2.0;
        return c;
    }
}

